#define _USE_MATH_DEFINES

#include <cstdio>
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <string>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <cassert>
#include <stack>
#include <cstdlib>
#include <bitset>
#include <cmath>

#define forn(i,n) for (int i = 0; i < int(n); ++i)
#define pb push_back
#define all(a) a.begin(),a.end()
#define sz(a) int(a.size())
#define mp make_pair

using namespace std;

typedef long long li;
typedef long double ld;

typedef pair<int,int> pt;
#define ft first
#define sc second

const int INF = int(1e9);
const li INF64 = li(1e18);
const ld EPS = 1e-9;

//#define TASK_NAME ""

int n;
const int N = 55;
int d[N][N];

bool read() {
	if (!(cin >> n))
		return false;
	
	forn (i, n)
		forn (j, n)
			cin >> d[i][j];

	return true;
}

vector<pair<int, int> > g[N];

int T, used[N];
int a[N];

void dfs(int v)
{
	used[v] = T;
	forn (i, g[v].size())
	{
		int to = g[v][i].ft;
		if (used[to] == T)
			continue;
		a[to] = min(a[v], g[v][i].sc);
		dfs(to);
	}
}

bool check()
{
	forn (i, n)
	{
		a[i] = INF;
		T++;
		dfs(i);
		a[i] = 0;
		forn (j, n)
			if (a[j] != d[i][j])
				return false;
	}
	return true;
}

int p[N];

int leader(int v)
{
	return p[v] == v ? v : p[v] = leader(p[v]);
}

bool merge(int a, int b)
{
	a = leader(a), b = leader(b);
	if (a == b)
		return false;
	if (rand() & 1)
		p[b] = a;
	else
		p[a] = b;
	return true;
}

void solve() {

	vector<int> order(n);

	forn (i, n)
		order[i] = i;

	vector<pair<int, pt> > e;
	forn (i, n)
		forn (j, n)
			if (i != j)
				e.pb(mp(d[i][j], mp(i, j)));
	sort(all(e));
	
	forn (it, 2)
	{
		forn (i, N)
			p[i] = i;
		forn (i, N)
			g[i].clear();

		vector<pair<int, pt> > cs;

		forn (i, sz(e))
		{
			if (merge(e[i].sc.ft, e[i].sc.sc))
			{
				cs.pb(e[i]);
				g[e[i].sc.ft].pb(mp(e[i].sc.sc, e[i].ft));
				g[e[i].sc.sc].pb(mp(e[i].sc.ft, e[i].ft));
			}
		}
		if (check())
		{
			cout << "YES" << endl;
			cout << n - 1 << endl;
			forn (i, n - 1)
				cout << cs[i].sc.ft + 1 << ' ' << cs[i].sc.sc + 1 << ' ' << cs[i].ft << endl;
			return;
		}
		reverse(all(e));
	}

	forn (it, 1000)
	{
		random_shuffle(all(order));

		forn (i, N)
			g[i].clear();

		forn (i, sz(order) - 1)
		{
			g[order[i]].pb(mp(order[i + 1], d[order[i]][order[i + 1]]));
			g[order[i + 1]].pb(mp(order[i], d[order[i]][order[i + 1]]));
		}

		if (check())
		{
			cout << "YES" << endl;
			cout << n - 1 << endl;
			forn (i, n - 1)
				cout << order[i] + 1 << ' ' << order[i + 1] + 1 << ' ' << d[order[i]][order[i + 1]] << endl;
			return;
		}
	}
	cout << "NO" << endl;
}

int main() {
#ifdef TASK_NAME
	freopen(TASK_NAME ".in", "r", stdin);
	freopen(TASK_NAME ".out", "w", stdout);
#endif

#ifdef _DEBUG
	freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
#endif

	while (read())
		solve();

	return 0;
}